import { EventSystem } from "../../../../../Core/Module/EventSystem/EventSystem";
import { AwakeSystem } from "../../../../../Core/Module/EventSystem/IAwakeSystem";
import { DestroySystem } from "../../../../../Core/Module/EventSystem/IDestroySystem";
import { LoadSystem } from "../../../../../Core/Module/EventSystem/ILoadSystem";
import { Log } from "../../../../../Core/Module/Log/Log";
import { NetServices } from "../../../../../Core/Module/Network/NetServices";
import { List } from "../../../../../Support/Share/Lib/Collections/List";
import { ExpandOf, FriendOf, GetCustomAttributes, GetTypeOf, MessageHandlerAttrData, MessageHandlerAttribute, ObjectSystemAttribute } from "../../../../../Decorator/Decorator";
import { IMHandler } from "../../../../Model/Share/Module/Message/IMHandler";
import { MessageDispatcherComponent, MessageDispatcherInfo } from "../../../../Model/Share/Module/Message/MessageDispatcherComponent";
import { Session } from "../../../../Model/Share/Module/Message/Session";
import { SceneType } from "../../../../../Core/Module/Entity/SceneType";


/**
 * 使用 Expand 扩展方法
 * 
 * 必须作出以下申明，才能调用对象的扩展方法
 */
declare module "../../../../Model/Share/Module/Message/MessageDispatcherComponent" {

    interface MessageDispatcherComponent {
        Load(): void;
        RegisterHandler(opcode: number, handler: MessageDispatcherInfo): void;
        Handle(session: Session, message: Object): void;
    }

}

@ExpandOf(MessageDispatcherComponent)
export class MessageDispatcherComponentSystem {

    private static Load(self: MessageDispatcherComponent): void {
        self.Handlers.Clear();

        let types = EventSystem.Instance.GetTypes(GetTypeOf(MessageHandlerAttribute));
        for (let type in types) {
            let clazz = types[type];
            let iMHandler = new clazz() as IMHandler;
            if (iMHandler == null) {
                Log.Error(`message handle ${clazz.Name} 需要继承 IMHandler`);
                continue;
            }
            let attrs = GetCustomAttributes(clazz);
            for (let attr of attrs) {
                let messageHandlerAttribute = attr as MessageHandlerAttrData;
                let iMHandlerParent = Object.getPrototypeOf(iMHandler) as IMHandler;
                let messageType = iMHandlerParent.GetMessageType();
                let opcode = NetServices.Instance.GetOpcode(messageType);
                if (opcode == 0) {
                    Log.Error(`消息opcode为0: ${messageType}`);
                    continue;
                }
                let messageDispatcherInfo = new MessageDispatcherInfo(messageHandlerAttribute.SceneType, iMHandler);
                self.RegisterHandler(opcode, messageDispatcherInfo);
            }
        }
    }

    private static RegisterHandler(self: MessageDispatcherComponent, opcode: number, handler: MessageDispatcherInfo): void {
        if (!self.Handlers.ContainsKey(opcode)) {
            self.Handlers.Add(opcode, new List());
        }
        self.Handlers.TryGetValue(opcode).Add(handler);
    }

    private static Handle(self: MessageDispatcherComponent, session: Session, message: Object): void {
        let opcode = NetServices.Instance.GetOpcode(GetTypeOf(message));
        let actions = self.Handlers.TryGetValue(opcode);
        if (!actions) {
            Log.Error(`消息没有处理: ${opcode} ${message}`);
            return;
        }
        let sceneType = session.DomainScene().SceneType;
        for (let messageDispatcherInfo of actions.ToArray()) {
            if (messageDispatcherInfo.SceneType != sceneType && messageDispatcherInfo.SceneType != SceneType.All) {
                continue;
            }
            try {
                // console.log(messageDispatcherInfo);
                // console.log(messageDispatcherInfo.IMHandler);
                // console.log(messageDispatcherInfo.IMHandler.Handle);

                messageDispatcherInfo.IMHandler.Handle(session, message);
            } catch (e) {
                Log.Error(e);
            }
        }
    }

}

@FriendOf(MessageDispatcherComponent)
@ObjectSystemAttribute()
export class MessageDispatcherComponentAwakeSystem extends AwakeSystem<MessageDispatcherComponent> {

    Awake(self: MessageDispatcherComponent): void {
        MessageDispatcherComponent.Instance = self;
        self.Load();
    }

}


@FriendOf(MessageDispatcherComponent)
@ObjectSystemAttribute()
export class MessageDispatcherComponentLoadSystem extends LoadSystem<MessageDispatcherComponent> {

    Load(self: MessageDispatcherComponent): void {
        self.Load();
    }

}

@FriendOf(MessageDispatcherComponent)
@ObjectSystemAttribute()
export class MessageDispatcherComponentDestroySystem extends DestroySystem<MessageDispatcherComponent> {

    Destroy(self: MessageDispatcherComponent): void {
        MessageDispatcherComponent.Instance = null;
        self.Handlers.Clear();
    }

}